#include <baker/Array.h>
#include <unittest++/UnitTest++.h>

using namespace baker;

SUITE( TestArray )
{
    TEST( append_n_prepend )
    {
        Array<int> intArray;

        intArray.append( 10 );
        intArray.append( 20 );
        intArray.prepend( 30 );

        CHECK( intArray.at( 0 ) == 30 );
        CHECK( intArray.at( 1 ) == 10 );
        CHECK( intArray.at( 2 ) == 20 );
    }

    TEST( indexOf )
    {
        Array<int> intArray;

        intArray.append( 10 );
        intArray.append( 20 );
        intArray.prepend( 30 );

        CHECK( intArray.indexOf( 10 ) == 1 );
        CHECK( intArray.indexOf( 20 ) == 2 );
        CHECK( intArray.indexOf( 30 ) == 0 );
    }

    TEST( remove )
    {
        Array<int> intArray;

        intArray.append( 10 );
        intArray.append( 20 );
        intArray.prepend( 30 );

        intArray.remove( 30 );

        CHECK( intArray.indexOf( 10 ) == 0 );
        CHECK( intArray.indexOf( 20 ) == 1 );
        CHECK( intArray.indexOf( 30 ) == ARRAY_NOT_FOUND );

        intArray.removeAt( 0 ); // remove 10

        CHECK( intArray.indexOf( 20 ) == 0 );

        intArray.removeAt( 0 ); // finally remove 20

        CHECK( intArray.length() == 0 );

    }

    TEST( removeFast )
    {
        Array<int> intArray;

        intArray.append( 10 );
        intArray.append( 20 );
        intArray.prepend( 30 );

        intArray.removeFast( 30 );

        CHECK( intArray.indexOf( 10 ) == 1 );
        CHECK( intArray.indexOf( 20 ) == 0 );
        CHECK( intArray.indexOf( 30 ) == ARRAY_NOT_FOUND );

        intArray.removeAtFast( 0 ); // remove 20

        CHECK( intArray.indexOf( 10 ) == 0 );

        intArray.removeAtFast( 0 ); // finally remove 10

        CHECK( intArray.length() == 0 );

    }

    static void TestArrayCallback   ( int i
                                    , int * sum
                                    )
    {
        *sum += i;
    }

    struct TestArrayCallbackFunctor
    {
        int * sum;

        void operator () ( int i )
        {
            *sum += i;
        }
    };

    TEST( foreach )
    {
        Array<int> intArray;

        intArray.append( 10 );
        intArray.append( 20 );
        intArray.append( 30 );

        // using a cb::functor
        {
            int sum = 0;

            foreach ( intArray
                    , cb::bind( cb::ptr_fun( TestArrayCallback ), &sum )
                    );

            CHECK_EQUAL( sum, 60 );
        }

        // using the cb::signal
        {
            int sum = 0;

            cb::signal< void, int & > callback;
            callback.connect( cb::bind( cb::ptr_fun( TestArrayCallback ), &sum ) );

            foreach ( intArray
                    , callback
                    );

            CHECK_EQUAL( sum, 60 );
        }

        // using a function
        {
            int sum = 0;

            TestArrayCallbackFunctor callback;
            callback.sum = &sum;

            foreach ( intArray
                    , callback
                    );

            CHECK_EQUAL( sum, 60 );
        }
    }

    TEST( indexOfMin )
    {
        Array<int> intArray;

        intArray.append( 30 );
        intArray.append( 10 );
        intArray.append( 10 );
        intArray.append( 10 );
        intArray.append( 20 );
        intArray.append( 20 );
        intArray.append( 40 );

        CHECK( indexOfMin( intArray, cb::ptr_fun( less<int> ) ) == 1 );
    }
}
